#!/usr/bin/python
# Copyright (c) 2012 The Native Client Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Tools for using Make to build bionic projects such as libc
"""

import process
import sys

from bionic_dirs import *
from file_update import Mkdir, Rmdir, Symlink, UpdateText
from replace import ReplaceArch, ReplaceText


def GetProjectPaths(out_dir, arch, project):
  srcpath = os.path.join(BIONIC_SRC, project)
  workpath = os.path.join(out_dir, 'bionic_$GCC_work')
  toolpath = os.path.join(out_dir, 'bionic_install')
  clangpath = os.path.join(toolpath, 'lib', 'clang', '3.4', 'lib')

  workpath = ReplaceArch(os.path.join(workpath, project), arch)
  instpath = ReplaceArch(os.path.join(toolpath, '$LIB'), arch)
  gccpath = ReplaceArch(os.path.join(clangpath, '$GCC-nacl'), arch)
  outpath = OUTPUT_ROOT
  out = {
    'bionic': BIONIC_SRC,
    'gcc': gccpath,
    'ins': instpath,
    'out': outpath,
    'src': srcpath,
    'tc': toolpath,
    'work': workpath,
  }
  return out


def ConfigureThirdParty(arch, project, args, clobber=False):
  srcpath = os.path.join(TOP_DIR, 'third_party', project)
  workpath = os.path.join(OUTPUT_ROOT, 'bionic_$GCC_work', project)
  workpath = ReplaceArch(workpath, arch)
  Mkdir(workpath)

  if not os.path.isfile(os.path.join(srcpath, 'configure')):
    process.Run(['autoreconf', '-f' ,'-i' ,'-Wall,no-obsolete'],
                cwd=srcpath, outfile=sys.stdout)

  CC = os.path.join(OUTPUT_ROOT, 'bionic_install', 'bin', arch + '-nacl-clang')
  CXX = os.path.join(OUTPUT_ROOT, 'bionic_install', 'bin', arch + '-nacl-clang++')
  args = ['sh',  os.path.join(srcpath, 'configure'), 
          'CC=' + CC, 'CXX=' + CXX, 
          '--prefix=' + os.path.join(workpath, 'out')] + args
  process.Run(args, cwd=workpath, outfile=sys.stdout)


def ConfigureProject(arch, project, clobber=False):
  paths = GetProjectPaths(OUTPUT_ROOT, arch, project)

  MAKEFILE_TEMPLATE = """
# Copyright (c) 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# GNU Makefile based on shared rules provided by the Native Client SDK.
# See README.Makefiles for more details.

NATIVE_CLIENT_PATH?=$(nacl_path)
TOOLCHAIN_PATH?=$(tc_path)
TOOLCHAIN_PREFIX:=$(TOOLCHAIN_PATH)/bin/$GCC-nacl-

CC:=$(TOOLCHAIN_PREFIX)clang
CXX:=$(TOOLCHAIN_PREFIX)clang++
AR:=$(TOOLCHAIN_PREFIX)ar
LD:=$(TOOLCHAIN_PREFIX)clang++
GCC:=$(nacl_path)/toolchain/linux_x86/nacl_$CPU_newlib/bin/$GCC-nacl-gcc

SRC_ROOT=$(src_path)
DST_ROOT=$(dst_path)
INS_ROOT=$(ins_path)
GCC_ROOT=$(gcc_path)

NACL_ARCH=$NACL
GCC_ARCH=$GCC

HELPER=$(out_path)/tools/$GCC/nacl_helper_bootstrap
SEL_LDR=$(out_path)/tools/$GCC/sel_ldr
IRT_CORE=$(out_path)/tools/$GCC/irt_core.nexe

MAKEFILE_DEPS:=$(bionic_path)/tc_bionic.mk
MAKEFILE_DEPS+=$(src_path)/Makefile

include $(bionic_path)/tc_bionic.mk
include $(src_path)/Makefile
"""
  remap = {
    '$(src_path)': paths['src'],
    '$(dst_path)': paths['work'],
    '$(gcc_path)': paths['gcc'],
    '$(ins_path)': paths['ins'],
    '$(tc_path)':  paths['tc'],
    '$(out_path)': paths['out'],
    '$(bionic_path)': paths['bionic'],
    '$(build_tc_path)': TOOLCHAIN_BUILD_DIR,
    '$(nacl_path)': NATIVE_CLIENT_DIR,
  }
  text = ReplaceText(MAKEFILE_TEMPLATE, [remap])
  text = ReplaceArch(text, arch)

  if clobber:
    print 'Clobbering Bionic project directory: ' + paths['work']
    Rmdir(paths['work'])

  Mkdir(paths['work'])
  Mkdir(paths['ins'])
  UpdateText(os.path.join(paths['work'], 'Makefile'), text)


def MakeProject(arch, project, targets=None, clobber=False, jobs=12):
  paths = GetProjectPaths(OUTPUT_ROOT, arch, project)
  workpath = paths['work']
  targets = targets or []
  targetlist = ' '.join(targets)
  print 'Building %s for %s at %s %s.' % (project, arch, workpath, targetlist)
  if clobber:
    args = ['make', '-j%d' % jobs, 'V=1', 'clean']
    if process.Run(args, cwd=workpath, outfile=sys.stdout):
      raise RuntimeError('Failed to clean %s for %s.\n' % (project, arch))

  args = ['make', '-j%d' % jobs, 'V=1'] + targets
  if process.Run(args, cwd=workpath, outfile=sys.stdout):
    print "Building at: " + workpath
    args = ['make', '-j1', 'V=1'] + targets
    process.Run(args, cwd=workpath, outfile=sys.stdout)
    raise RuntimeError('Failed to build %s for %s.\n' % (project, arch))
  print 'Done with %s for %s.\n' % (project, arch)

